import colorString from 'color-string';
import { NIcon } from 'naive-ui';
import type { Component } from 'vue';
import { isFunction, isNil, isObject, isString, set } from 'lodash-es';

import SvgIcon from '@/components/svg-icon/index.vue';
import ColorIcon from '@/components/color-icon/index.vue';

/**
 * 渲染一个图标
 *
 * @param icon 图标名称
 * @param size 图标大小
 * @param classNames 样式类名
 */
export function renderIcon(icon: string | Component, size?: number, classNames?: string) {
  if (isString(icon) && icon.startsWith('svg__')) {
    return () => h(SvgIcon, {
      name: icon.split('svg__')[1],
      size,
    });
  } else if (isString(icon)) {
    return () => h(ColorIcon, {
      value: icon,
      size,
    });
  } else {
    return () => createIcon(icon, size, classNames);
  }
}

/**
 * 创建一个图标VNode
 *
 * @param icon 图标名称
 * @param size 图标大小
 * @param classNames 样式类名
 */
export function createIcon(icon: string | Component, size?: number, classNames?: string) {
  return h(
    NIcon,
    {
      class: classNames,
      size,
    },
    {
      default: () => (isString(icon) ? h(resolveComponent(icon)) : h(icon)),
    },
  );
}

/**
 * 判断一个字符串是否为颜色
 *
 * @param color 颜色字符串
 */
export function isColorString(color: string) {
  return colorString.get(color) != null;
}

/**
 * 判断一个函数是否为异步函数
 *
 * @param func 函数
 */
export function isAsyncFunction(func: any) {
  return Object.prototype.toString.call(func) == '[object AsyncFunction]';
}

const speakingText = ref('');
const { speak } = useSpeechSynthesis(speakingText, {
  rate: 1,
  pitch: 1,
  volume: 1,
  lang: 'zh-CN',
});

/**
 * 语音合成
 *
 * @param text 文本
 */
export function speakText(text: string) {
  speakingText.value = text;

  if (speakingText.value) {
    speak();
  }
}

const nameAliasRegExp = /\s+as\s+/i;

/**
 * 解析名称别名
 *
 * @param name 名称
 */
export function parseNameAlias(name: string) {
  const tokens = name.split(nameAliasRegExp);
  return tokens.length == 2 ? tokens : [tokens[0], tokens[0]];
}

/**
 * 解析一段JavaScript代码
 *
 * @param code JavaScript代码
 */
export function parseJavaScriptCode(code: string) {
  // eslint-disable-next-line no-new-func
  return Function(`'use strict'; return (${code})`)();
}

/**
 * 过滤对象参数
 * @param values
 */
export function filterObjectParams(values: Recordable) {
  if (!isObject(values)) {
    return {};
  }
  const res: Recordable = {};
  for (const item of Object.entries(values)) {
    let [, value] = item;
    const [key] = item;
    if (
      !key
      // || (isArray(value) && value.length === 0)
      || isFunction(value)
      || isNil(value)
    ) {
      continue;
    }
    if (isString(value)) {
      value = value.trim();
    }
    set(res, key, value);
  }
  return res;
}
